using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediatR;
using Microsoft.Extensions.Logging;
using RBAC.Domain.Dto.Output;
using RBAC.Domain.MaterialManage;
using RBAC.Domain.OutboundManage;
using RBAC.ErrorCode;
using RBAC.Interstructrue.Base;
using RBAC.Write.Api.Application.Command.ERP.OutboundManagement;
using RBAC.Write.Api.Application.Dto.ERP;

namespace RBAC.Write.Api.Application.Handler.ERP.OutboundManagement
{
    public class UpdateSalesOutboundHandler : IRequestHandler<UpdateSalesOutboundCommand, APIResult<bool>>
    {
        private readonly IBaseRepository<SalesOutbound> outboundRepo;
        private readonly IBaseRepository<SalesOutboundDetail> detailRepo;
        private readonly IBaseRepository<Mater> materRepo;
        private readonly ILogger<UpdateSalesOutboundHandler> logger;

        public UpdateSalesOutboundHandler(
            IBaseRepository<SalesOutbound> outboundRepo,
            IBaseRepository<SalesOutboundDetail> detailRepo,
            IBaseRepository<Mater> materRepo,
            ILogger<UpdateSalesOutboundHandler> logger)
        {
            this.outboundRepo = outboundRepo;
            this.detailRepo = detailRepo;
            this.materRepo = materRepo;
            this.logger = logger;
        }

        public Task<APIResult<bool>> Handle(UpdateSalesOutboundCommand request, CancellationToken cancellationToken)
        {
            var result = new APIResult<bool>();
            try
            {
                var dto = request.Data;
                if (dto == null || dto.Details == null || dto.Details.Count == 0)
                {
                    result.Code = APIEnums.Fail;
                    result.Msg = "明细不能为空";
                    result.Data = false;
                    return Task.FromResult(result);
                }

                var header = outboundRepo.GetFirstOrDefault("Id = @Id AND IsDeleted = false", new { Id = request.Id });
                if (header == null)
                {
                    result.Code = APIEnums.Fail;
                    result.Msg = "单据不存在";
                    result.Data = false;
                    return Task.FromResult(result);
                }
                // 仅开立状态允许编辑
                if (!string.Equals(header.OrderStatus, "开立", StringComparison.OrdinalIgnoreCase))
                {
                    result.Code = APIEnums.Fail;
                    result.Msg = "仅开立状态的销售出库单可编辑";
                    result.Data = false;
                    return Task.FromResult(result);
                }

                var materIds = dto.Details.Select(d => d.MaterId).Distinct().ToList();
                var inClause = string.Join(",", materIds.Select((_, i) => $"@Id{i}"));
                var inParams = materIds.Select((id, i) => new { Key = $"@Id{i}", Value = id })
                    .ToDictionary(x => x.Key, x => (object)x.Value);
                var maters = materRepo.GetAll($"Id IN ({inClause})", inParams);
                var valid = new HashSet<long>(maters.Select(m => m.Id));
                var missing = materIds.Where(id => !valid.Contains(id)).ToList();
                if (missing.Any())
                {
                    result.Code = APIEnums.Fail;
                    result.Msg = $"存在无效物料ID: {string.Join(",", missing)}";
                    result.Data = false;
                    return Task.FromResult(result);
                }

                var now = DateTime.Now;
                var begin = "START TRANSACTION;";
                var updateHeader = @"UPDATE SalesOutbound SET 
OrderCode=@OrderCode, OrderType=@OrderType, BusinessType=@BusinessType, Period=@Period,
CustomerCode=@CustomerCode, CustomerName=@CustomerName, OrderDate=@OrderDate, BusinessStatus=@BusinessStatus,
Warehouse=@Warehouse, OrderStatus=@OrderStatus, DeliveryNo=@DeliveryNo, DeliveryType=@DeliveryType,
BusinessDept=@BusinessDept, BusinessPerson=@BusinessPerson, Remark=@Remark, CreateUser=@CreateUser
WHERE Id=@Id AND IsDeleted=false;";
                var deleteDetails = "DELETE FROM SalesOutboundDetail WHERE SalesOutboundId=@Id;";
                var insertDetails = new List<string>();
                for (int i = 0; i < dto.Details.Count; i++)
                {
                    insertDetails.Add($"INSERT INTO SalesOutboundDetail (SalesOutboundId, MaterId, CopyTradCode, Num, Remark, CreateUser, CreateTime, IsDeleted) VALUES (@Id, @D{i}_MaterId, @D{i}_CopyTradCode, @D{i}_Num, @D{i}_Remark, @CreateUser, @CreateTime, false);");
                }
                var commit = "COMMIT; SELECT 1;";

                var fullSql = string.Join("\n", new[] { begin, updateHeader, deleteDetails, string.Join("\n", insertDetails), commit });

                var param = new Dictionary<string, object?>
                {
                    ["Id"] = request.Id,
                    ["OrderCode"] = dto.OrderCode,
                    ["OrderType"] = dto.OrderType ?? header.OrderType,
                    ["BusinessType"] = dto.BusinessType ?? header.BusinessType,
                    ["Period"] = dto.Period,
                    ["CustomerCode"] = dto.CustomerCode,
                    ["CustomerName"] = dto.CustomerName,
                    ["OrderDate"] = dto.OrderDate ?? header.OrderDate ?? now,
                    ["BusinessStatus"] = dto.BusinessStatus ?? header.BusinessStatus ?? "正常",
                    ["Warehouse"] = dto.Warehouse,
                    ["OrderStatus"] = header.OrderStatus ?? "开立",
                    ["DeliveryNo"] = dto.DeliveryNo,
                    ["DeliveryType"] = dto.DeliveryType,
                    ["BusinessDept"] = dto.BusinessDept,
                    ["BusinessPerson"] = dto.BusinessPerson,
                    ["Remark"] = dto.Remark,
                    ["CreateUser"] = dto.CreateUser,
                    ["CreateTime"] = now
                };
                for (int i = 0; i < dto.Details.Count; i++)
                {
                    var d = dto.Details[i];
                    param[$"D{i}_MaterId"] = d.MaterId;
                    param[$"D{i}_CopyTradCode"] = d.CopyTradCode;
                    param[$"D{i}_Num"] = d.Num;
                    param[$"D{i}_Remark"] = d.Remark;
                }

                try
                {
                    var ok = outboundRepo.QueryFirstOrDefault<int>(fullSql, param);
                    result.Code = APIEnums.Success;
                    result.Msg = "修改销售出库成功";
                    result.Data = ok == 1;
                }
                catch (Exception ex)
                {
                    outboundRepo.Execute("ROLLBACK;");
                    logger.LogError(ex, "修改销售出库失败: {Message}", ex.Message);
                    result.Code = APIEnums.Error;
                    result.Msg = "修改销售出库失败";
                    result.Data = false;
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "修改销售出库异常: {Message}", ex.Message);
                result.Code = APIEnums.Error;
                result.Msg = "修改销售出库异常";
                result.Data = false;
            }

            return Task.FromResult(result);
        }
    }
}
